<!doctype html>
<title>Navigating to a selector fragment directive</title>
<meta charset=utf-8>
<link rel="help" href="https://github.com/WICG/scroll-to-text-fragment/blob/main/EXTENSIONS.md#proposed-solution">
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/common/utils.js"></script>
<script src="stash.js"></script>
<!--
  This test suite performs scroll to selector navigations to
  scroll-to-selector-fragment-target.html and then checks the results, which are
  communicated back from the target page via the WPT Stash server (see stash.py).
-->
<script>
let test_cases = [
  {
    description: 'Basic selector test',
    fragment: '#:~:selector(type=CssSelector,value=svg[id=cat])',
    expect_position: 'cat'
  },
  {
    description: 'value= comes before type=',
    fragment: '#:~:selector(value=svg[id=cat],type=CssSelector)',
    expect_position: 'cat'
  },
  {
    description: 'Invalid selector directive 1',
    fragment: '#:~:selector(ignorethisvalue=type=)',
    expect_position: 'top'
  },
  {
    description: 'Invalid selector directive 2',
    fragment: '#:~:selector()',
    expect_position: 'top'
  },
  {
    description: 'Invalid selector directive 3',
    fragment: '#:~:selector(type=,value=)',
    expect_position: 'top'
  },
  {
    description: 'Invalid selector directive 4',
    fragment: '#:~:selector(value=,type=)',
    expect_position: 'top'
  },
  {
    description: 'Value is empty, technically a valid selector, though it wouldn\'t select antyhing',
    fragment: '#:~:selector(value=,type=CssSelector)',
    expect_position: 'top'
  },
  {
    description: 'There is a type= in css selector value',
    fragment: '#:~:selector(value=input[type=button],type=CssSelector)',
    expect_position: 'input-button'
  },
  {
    description: 'There is a type= in css selector value, value is URLEncoded',
    // fragment: '#:~:selector(value=input[type=button],type=CssSelector)',
    fragment: '#:~:selector(value=input%5Btype%3Dbutton%5D,type=CssSelector)',
    expect_position: 'input-button'
  },
  {
    description: 'Should parse 2 selector directives',
    fragment: '#:~:selector(type=CssSelector,value=svg[id=cat])&selector(type=CssSelector,value=input[type=button])',
    expect_position: 'cat'
  },
  {
    description: 'Ignore other parts, only parse type= and value=',
    fragment: '#:~:selector(type=CssSelector,lorem_part,value=svg[id=cat])',
    expect_position: 'cat'
  },
  {
    description: 'Don\'t accept ambiguous directive, don\'t allow two type= parts',
    fragment: '#:~:selector(type=CssSelector,type=SomethingElse,value=svg[id=cat])',
    expect_position: 'top'
  },
  {
    description: 'Don\'t accept ambiguous directive, don\'t allow two value= parts',
    fragment: '#:~:selector(type=CssSelector,value=input[type=button],value=svg[id=cat])',
    expect_position: 'top'
  },
  // {
  //   description: 'a comma in value= part should be encoded',
  //   fragment: '#:~:selector(value=svg[id%3Dcat%2Cdog],type=CssSelector)',
  //   expect_position: 'cat'
  // },
  {
    description: 'Should not allow multiple value= parts v1',
    fragment: '#:~:selector(value=,type=CssSelector,value=img) ',
    expect_position: 'top'
  },
  {
    description: 'Should not allow multiple value= parts v2',
    fragment: '#:~:selector(value=img,value=,type=CssSelector) ',
    expect_position: 'top'
  }
];

for (const test_case of test_cases) {
  promise_test(t => new Promise((resolve, reject) => {
    let key = token();

    test_driver.bless('Open a URL with a selector fragment directive', () => {
      window.open(`scroll-to-selector-fragment-target.html?key=${key}${test_case.fragment}`, '_blank', 'noopener');
    });

    fetchResults(key, resolve, reject);
  }).then(data => {
    // If the position is not 'top', the :target element should be the positioned element.
    assert_true(data.scrollPosition == 'top' || data.target == data.scrollPosition);
    assert_equals(data.href.indexOf(':~:'), -1, 'Expected fragment directive to be stripped from the URL.');
    assert_equals(data.scrollPosition, test_case.expect_position,
                  `Expected ${test_case.fragment} (${test_case.description}) to scroll to ${test_case.expect_position}.`);
  }), `Test navigation with fragment: ${test_case.description}.`);
}
</script>
